library(tidyverse) # For data manipulation and visualization
library(readr) # For reading CSV data
library(lubridate) # For date manipulation
library(caret) # For creating training and test sets, and modeling
library(plotly)
library(ggplot2)
library(readr)
library(RColorBrewer)
library(readxl)
library(scales)
library(hexbin)
library(viridis)
Warning: package ‘viridis’ was built under R version 4.2.3Loading required package: viridisLite
Warning: package ‘viridisLite’ was built under R version 4.2.3
Attaching package: ‘viridis’
The following object is masked from ‘package:scales’:
viridis_pal
party_dictionary <- data.frame(
Original = c("ACE","AKI","AIC","AIP","AMP","APF","AE","CIT","CMD","CMP","COM","CNC","CRV","CON","CST","COU","DCG","DNL","DEM","D/C","DFL","DGR","FED","FLP","FRE","GWP","GRT","GRE","GR","HRP","IDP","IND","IAP","ICD","IGR","IP","IDE","IGD","JCN","JUS","LRU","LBR","LFT","LBL","LIB","LBU","MTP","NDP","NLP","NA","NJC","NPP","NPA","NOP","NNE","N","NON","OE","OTH","PG","PSL","PAF","PFP","PFD","POP","PPY","PCH","PPD","PRO","NAP","PRI","RUP","REF","REP","RES","RTL","SEP","SLP","SUS","SOC","SWP","TX","TWR","TEA","THD","LAB","USP","UST","UN","UC","UNI","UNK","VET","WTP","W"),
Label = c("Ace Party","Alaskan Independence Party","American Independent Conservative","American Independent Party","American Party","American People's Freedom Party","Americans Elect","Citizens' Party","Commandments Party","Commonwealth Party of the U.S.","Communist Party","Concerned Citizens Party Of Connecticut","Conservative Party","Constitution Party","Constitutional","Country","D.C. Statehood Green Party","Democratic -Nonpartisan League","Democratic Party","Democratic/Conservative","Democratic-Farmer-Labor","Desert Green Party","Federalist","Freedom Labor Party","Freedom Party","George Wallace Party","Grassroots","Green Party","Green-Rainbow","Human Rights Party","Independence Party","Independent","Independent American Party","Independent Conservative Democratic","Independent Green","Independent Party","Independent Party of Delaware","Industrial Government Party","Jewish/Christian National","Justice Party","La Raza Unida","Labor Party","Less Federal Taxes","Liberal Party","Libertarian Party","Liberty Union Party","Mountain Party","National Democratic Party","Natural Law Party","New Alliance","New Jersey Conservative Party","New Progressive Party","No Party Affiliation","No Party Preference","None","Nonpartisan","Non-Party","One Earth Party","Other","Pacific Green","Party for Socialism and Liberation","Peace And Freedom","Peace And Freedom Party","Peace Freedom Party","People Over Politics","People's Party","Personal Choice Party","Popular Democratic Party","Progressive Party","Prohibition Party","Puerto Rican Independence Party","Raza Unida Party","Reform Party","Republican Party","Resource Party","Right To Life","Socialist Equality Party","Socialist Labor Party","Socialist Party","Socialist Party U.S.A.","Socialist Workers Party","Taxpayers","Taxpayers Without Representation","Tea Party","Theo-Democratic","U.S. Labor Party","U.S. People's Party","U.S. Taxpayers Party","Unaffiliated","United Citizen","United Party","Unknown","Veterans Party","We the People","Write-In")
)
cand_data <- read.csv2(file = "C:/Users/18137/Downloads/candidate_summary_2020.csv", sep = "," , )
cand_data$Total_Contribution <- as.numeric(cand_data$Total_Contribution)
cand_data$Total_Receipt <- as.numeric(cand_data$Total_Receipt)
cand_data <- cand_data %>%
left_join(party_dictionary, by = c("Cand_Party_Affiliation" = "Original")) %>%
# Optionally, you might want to remove the original column and rename the new one
select(-Cand_Party_Affiliation) %>%
rename(Cand_Party_Affiliation = Label)
election_results <- read_excel("C:/Users/18137/Downloads/federalelections2020.xlsx")
New names:
senate_results <- read_excel("C:/Users/18137/Downloads/federalelections2020.xlsx", sheet = "12. US Senate Results by State")
house_results <- read_excel("C:/Users/18137/Downloads/federalelections2020.xlsx", sheet = "13. US House Results by State")
pres_primary_results <- read_excel("C:/Users/18137/Downloads/federalelections2020.xlsx", sheet = "9. 2020 Pres General Results")
senate_results <- senate_results %>%
mutate(Win_Lose = as.numeric('GE Winner Indicator' == "W"))
house_results <- house_results %>%
mutate(Win_Lose = as.numeric('GE Winner Indicator' == "W"))
pres_primary_results <- pres_primary_results %>%
mutate(Win_Lose = as.numeric('Winner_Indicator' == "W"))
cand_data <- cand_data %>% group_by(Cand_Party_Affiliation) %>% filter(Total_Receipt > 0)
all_election_results <- bind_rows(senate_results, house_results, pres_primary_results)
final_data <- cand_data %>%
left_join(all_election_results, by = c("Cand_Id" = "FEC ID"))
final_data$Win_Lose[is.na(final_data$Win_Lose)] <- 0
head(final_data)
merged_data <- final_data %>%
mutate(Total_Contribution = if_else(is.na(Total_Contribution), median(Total_Contribution, na.rm = TRUE), Total_Contribution))
summary(merged_data)
Link_Image Cand_Name Cand_Id Cand_Office Cand_Office_St
Length:2938 Length:2938 Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character Mode :character
Cand_Office_Dist Cand_Incumbent_Challenger_Open_Seat Total_Receipt Total_Disbursement
Min. : 0.000 Length:2938 Min. :1.000e+00 Length:2938
1st Qu.: 0.000 Class :character 1st Qu.:2.124e+04 Class :character
Median : 4.000 Mode :character Median :1.587e+05 Mode :character
Mean : 7.642 Mean :3.534e+07
3rd Qu.:10.750 3rd Qu.:1.560e+06
Max. :53.000 Max. :1.125e+09
Cash_On_Hand_COP Debt_Owed_By_Committee Coverage_End_Date Cand_Street_1 Cand_Street_2
Length:2938 Length:2938 Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character Mode :character
Cand_City Cand_State Cand_Zip Individual_Itemized_Contribution
Length:2938 Length:2938 Min. : 0 Length:2938
Class :character Class :character 1st Qu.: 22314 Class :character
Mode :character Mode :character Median : 48216 Mode :character
Mean : 26963948
3rd Qu.: 82414
Max. :995100298
NA's :144
Individual_Unitemized_Contribution Individual_Contribution Other_Committee_Contribution
Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character
Mode :character Mode :character Mode :character
Party_Committee_Contribution Cand_Contribution Total_Contribution
Length:2938 Length:2938 Min. :0.000e+00
Class :character Class :character 1st Qu.:1.254e+04
Mode :character Mode :character Median :9.946e+04
Mean :2.524e+07
3rd Qu.:1.226e+06
Max. :1.090e+09
Transfer_From_Other_Auth_Committee Cand_Loan Other_Loan Total_Loan
Length:2938 Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
Offsets_To_Operating_Expenditure Offsets_To_Fundraising Offsets_To_Leagal_Accounting
Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character
Mode :character Mode :character Mode :character
Other_Receipts Operating_Expenditure Exempt_Legal_Accounting_Disbursement
Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character
Mode :character Mode :character Mode :character
Fundraising_Disbursement Transfer_To_Other_Auth_Committee Cand_Loan_Repayment Other_Loan_Repayment
Length:2938 Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
Total_Loan_Repayment Individual_Refund Party_Committee_Refund Other_Committee_Refund
Length:2938 Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
Total_Contribution_Refund Other_Disbursements Net_Contribution Net_Operating_Expenditure
Length:2938 Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
Cash_On_Hand_BOP Debt_Owe_To_Committee Coverage_Start_Date Cand_Party_Affiliation 1
Length:2938 Length:2938 Length:2938 Length:2938 Min. : 3.0
Class :character Class :character Class :character Class :character 1st Qu.: 390.8
Mode :character Mode :character Mode :character Mode :character Median :1102.0
Mean :1511.8
3rd Qu.:2579.2
Max. :4036.0
NA's :574
STATE ABBREVIATION STATE DISTRICT (I) Incumbent Indicator
Length:2938 Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character
CANDIDATE NAME (First) CANDIDATE NAME (Last) CANDIDATE NAME TOTAL VOTES PARTY
Length:2938 Length:2938 Length:2938 Length:2938 Length:2938
Class :character Class :character Class :character Class :character Class :character
Mode :character Mode :character Mode :character Mode :character Mode :character
PRIMARY VOTES PRIMARY % RUNOFF VOTES RUNOFF % GENERAL VOTES
Length:2938 Min. :0.0001 Min. : 1570 Min. :0.2405 Length:2938
Class :character 1st Qu.:0.1105 1st Qu.: 8528 1st Qu.:0.4304 Class :character
Mode :character Median :0.3107 Median : 16102 Median :0.5116 Mode :character
Mean :0.4042 Mean : 48039 Mean :0.5072
3rd Qu.:0.6751 3rd Qu.: 33884 3rd Qu.:0.5937
Max. :1.0000 Max. :502516 Max. :0.7595
NA's :1344 NA's :2888 NA's :2888
GENERAL % GE RUNOFF ELECTION VOTES (GA, LA) GE RUNOFF ELECTION % (GA, LA)
Min. :0.0000 Min. :2195841 Min. :0.4896
1st Qu.:0.0135 1st Qu.:2210195 1st Qu.:0.4928
Median :0.3874 Median :2242451 Median :0.5000
Mean :0.3436 Mean :2242464 Mean :0.5000
3rd Qu.:0.5628 3rd Qu.:2274721 3rd Qu.:0.5072
Max. :1.0000 Max. :2289113 Max. :0.5104
NA's :1472 NA's :2934 NA's :2934
COMBINED GE PARTY TOTALS (when applicable) COMBINED % (when applicable) PE WINNER INDICATOR
Mode:logical Mode:logical Length:2938
NA's:2938 NA's:2938 Class :character
Mode :character
GE WINNER INDICATOR FOOTNOTES Win_Lose GE RUNOFF ELECTION VOTES (GA, GU, LA)
Length:2938 Length:2938 Min. :0 Min. : 7090
Class :character Class :character 1st Qu.:0 1st Qu.: 9623
Mode :character Mode :character Median :0 Median :20296
Mean :0 Mean :24216
3rd Qu.:0 3rd Qu.:34889
Max. :0 Max. :49183
NA's :2934
GE RUNOFF ELECTION % (GA, GU, LA) COMBINED GE PARTY TOTALS (CT, NY) COMBINED % (CT, NY)
Min. :0.3798 Min. : 3164 Min. :0.0094
1st Qu.:0.3978 1st Qu.:149449 1st Qu.:0.4321
Median :0.5000 Median :181021 Median :0.5445
Mean :0.5000 Mean :170471 Mean :0.5273
3rd Qu.:0.6022 3rd Qu.:206310 3rd Qu.:0.5929
Max. :0.6202 Max. :234933 Max. :0.9079
NA's :2934 NA's :2836 NA's :2836
GENERAL ELECTION DATE FIRST NAME LAST NAME LAST NAME, FIRST GENERAL RESULTS
Min. :2020-11-03 Length:2938 Length:2938 Length:2938 Min. : 1
1st Qu.:2020-11-03 Class :character Class :character Class :character 1st Qu.: 181
Median :2020-11-03 Mode :character Mode :character Mode :character Median : 3404
Mean :2020-11-03 Mean : 376663
3rd Qu.:2020-11-03 3rd Qu.: 80633
Max. :2020-11-03 Max. :11110639
NA's :2516 NA's :2518
TOTAL VOTES # COMBINED GE PARTY TOTALS (NY) COMBINED % (NY) WINNER INDICATOR ELECTORAL VOTES
Min. : NA Length:2938 Min. :0.3774 Length:2938 Length:2938
1st Qu.: NA Class :character 1st Qu.:0.3774 Class :character Class :character
Median : NA Mode :character Median :0.4930 Mode :character Mode :character
Mean :NaN Mean :0.4930
3rd Qu.: NA 3rd Qu.:0.6087
Max. : NA Max. :0.6087
NA's :2938 NA's :2932
# Ensure Win_Lose is a factor for logistic regression
merged_data$Win_Lose <- as.factor(merged_data$Win_Lose)
# Fit the model
model <- glm(Win_Lose ~ Total_Contribution, data = merged_data, family = binomial(),control = glm.control(maxit = 10000))
Warning: glm.fit: fitted probabilities numerically 0 or 1 occurred
# Check the summary
summary(model)
Call:
glm(formula = Win_Lose ~ Total_Contribution, family = binomial(),
data = merged_data, control = glm.control(maxit = 10000))
Deviance Residuals:
Min 1Q Median 3Q Max
-2.107e-08 -2.107e-08 -2.107e-08 -2.107e-08 -2.107e-08
Coefficients:
Estimate Std. Error z value Pr(>|z|)
(Intercept) -3.057e+01 4.951e+04 -0.001 1
Total_Contribution -1.963e-22 3.847e-04 0.000 1
(Dispersion parameter for binomial family taken to be 1)
Null deviance: 0.0000e+00 on 2937 degrees of freedom
Residual deviance: 1.3047e-12 on 2936 degrees of freedom
AIC: 4
Number of Fisher Scoring iterations: 29
set.seed(123) # for reproducibility
training_samples <- createDataPartition(merged_data$Win_Lose, p = 0.8, list = FALSE)
train_data <- merged_data[training_samples, ]
test_data <- merged_data[-training_samples, ]
# Predict on test set
predictions <- predict(model, test_data, type = "response")
predicted_class <- if_else(predictions > 0.5, 1, 0)
# Adjusting the sampling method to ensure stratification
training_samples <- createDataPartition(merged_data$Win_Lose, p = 0.8, list = TRUE, times = 1)
train_data <- merged_data[training_samples[[1]], ]
test_data <- merged_data[-training_samples[[1]], ]
test_data$Win_Lose <- factor(test_data$Win_Lose, levels = c("0", "1"))
# Ensure predicted_class is a factor with both levels
predicted_class <- factor(predicted_class, levels = c("0", "1"))
confusionMatrix(predicted_class, test_data$Win_Lose)
Confusion Matrix and Statistics
Reference
Prediction 0 1
0 587 0
1 0 0
Accuracy : 1
95% CI : (0.9937, 1)
No Information Rate : 1
P-Value [Acc > NIR] : 1
Kappa : NaN
Mcnemar's Test P-Value : NA
Sensitivity : 1
Specificity : NA
Pos Pred Value : NA
Neg Pred Value : NA
Prevalence : 1
Detection Rate : 1
Detection Prevalence : 1
Balanced Accuracy : NA
'Positive' Class : 0
# Calculate accuracy or other performance metrics
accuracy <- sum(predicted_class == test_data$Win_Lose) / nrow(test_data)
print(paste("Accuracy:", accuracy))
[1] "Accuracy: 1"
conTotal <- cand_data$Total_Contribution
fig1 <- cand_data %>%
ggplot(aes(conTotal, Cand_State)) + geom_col(aes(fill = cand_data$Cand_State)) + scale_x_continuous(labels = scales::label_dollar(prefix = "$"))
ggplotly(fig1)
cand_by_affiliation_Total_Receipt <- cand_data %>%
group_by(Cand_Party_Affiliation) %>%
filter(Total_Receipt > 0) %>%
arrange(Total_Receipt)
cand_by_affiliation_Total_Receipt <- data.frame(cand_by_affiliation_Total_Receipt$Cand_Party_Affiliation, cand_by_affiliation_Total_Receipt$Total_Receipt)
arg_data <- aggregate(cand_by_affiliation_Total_Receipt$cand_by_affiliation_Total_Receipt.Total_Receipt,
list(Category = cand_by_affiliation_Total_Receipt$cand_by_affiliation_Total_Receipt.Cand_Party_Affiliation),
sum)
arg_data <- arg_data %>% top_n(2)
ggplot(arg_data, aes(x = Category, y = x)) + geom_col(aes(fill = Category)) + scale_y_continuous(labels = scales::label_dollar(prefix = "$", suffix = ""))
# Assuming 'cand_data' is your data frame and it has been loaded into your R session
distinct_parties <- cand_data %>%
select(Cand_Party_Affiliation) %>% # Select the column of interest
distinct() %>% # Get distinct/unique entries
arrange(Cand_Party_Affiliation) # Optional: arrange them alphabetically
# To view the distinct party affiliations
print(distinct_parties)
receipt_data <- cand_data %>%
group_by(Cand_Party_Affiliation) %>%
summarize(Total_Receipt = sum(Total_Receipt, na.rm = TRUE)) %>%
filter(Total_Receipt > 0) %>%
ggplot(aes(x = Cand_Party_Affiliation, y = Total_Receipt, fill = Cand_Party_Affiliation)) +
geom_bar(stat = "identity") +
scale_fill_viridis(discrete = TRUE, option = "M") +
scale_y_log10(labels = label_dollar(scale = 1)) +
labs(x = "Party Affiliation",
y = "Log of Total Receipts (Dollars)",
title = "Total Receipts by Party Affiliation") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5))
plotly_receipt_data <- ggplotly(receipt_data)
plotly_receipt_data
Congressional_data <- cand_data %>%
group_by(Cand_Office) %>%
filter(Cand_Office != "P") %>%
arrange(Total_Contribution)
Congressional_data <- aggregate(Congressional_data$Total_Contribution,
list(Category = Congressional_data$Cand_Office ),
sum)
president_data <- cand_data %>%
group_by(Cand_Office) %>%
filter(Cand_Office == "P") %>%
arrange(Total_Contribution)
Congressional_data %>% ggplot(aes(x = x, y = Category)) + geom_col(aes(fill = Category)) + scale_x_continuous(label = scales::label_dollar(prefix = "$"))
fig1 <- cand_data %>%
group_by(Cand_State) %>%
summarise(Total_Contribution = sum(Total_Contribution)) %>%
filter(Total_Contribution > 0) %>% # Filtering out zeros
ggplot(aes(x = Cand_State, y = Total_Contribution, fill = Cand_State)) +
geom_bar(stat = "identity") +
scale_fill_viridis(discrete = TRUE, option = "D") + # Using viridis for discrete color mapping
scale_y_log10(labels = scales::label_dollar(scale = 1)) + # Formatting y-axis as dollar values
theme_minimal() +
labs(title = "Total Contributions by State",
y = "Log of Total Contributions (Dollars)",
x = "State") +
theme(axis.text.x = element_text(angle = 90, hjust = 1, vjust = 0.5)) # Vertical x-axis labels
# Convert to Plotly interactive plot
plotly_fig1 <- ggplotly(fig1)
plotly_fig1
LS0tDQp0aXRsZTogIkZFQyBBbmFseXNpcyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCg0KDQpgYGB7cn0NCg0KbGlicmFyeSh0aWR5dmVyc2UpICAjIEZvciBkYXRhIG1hbmlwdWxhdGlvbiBhbmQgdmlzdWFsaXphdGlvbg0KbGlicmFyeShyZWFkcikgICAgICAjIEZvciByZWFkaW5nIENTViBkYXRhDQpsaWJyYXJ5KGx1YnJpZGF0ZSkgICMgRm9yIGRhdGUgbWFuaXB1bGF0aW9uDQpsaWJyYXJ5KGNhcmV0KSAgICAgICMgRm9yIGNyZWF0aW5nIHRyYWluaW5nIGFuZCB0ZXN0IHNldHMsIGFuZCBtb2RlbGluZw0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJlYWRyKQ0KbGlicmFyeShSQ29sb3JCcmV3ZXIpDQpsaWJyYXJ5KHJlYWR4bCkNCmxpYnJhcnkoc2NhbGVzKQ0KbGlicmFyeShoZXhiaW4pDQpsaWJyYXJ5KHZpcmlkaXMpDQoNCg0KYGBgDQoNCmBgYHtyfQ0KDQpwYXJ0eV9kaWN0aW9uYXJ5IDwtIGRhdGEuZnJhbWUoDQogIE9yaWdpbmFsID0gYygiQUNFIiwiQUtJIiwiQUlDIiwiQUlQIiwiQU1QIiwiQVBGIiwiQUUiLCJDSVQiLCJDTUQiLCJDTVAiLCJDT00iLCJDTkMiLCJDUlYiLCJDT04iLCJDU1QiLCJDT1UiLCJEQ0ciLCJETkwiLCJERU0iLCJEL0MiLCJERkwiLCJER1IiLCJGRUQiLCJGTFAiLCJGUkUiLCJHV1AiLCJHUlQiLCJHUkUiLCJHUiIsIkhSUCIsIklEUCIsIklORCIsIklBUCIsIklDRCIsIklHUiIsIklQIiwiSURFIiwiSUdEIiwiSkNOIiwiSlVTIiwiTFJVIiwiTEJSIiwiTEZUIiwiTEJMIiwiTElCIiwiTEJVIiwiTVRQIiwiTkRQIiwiTkxQIiwiTkEiLCJOSkMiLCJOUFAiLCJOUEEiLCJOT1AiLCJOTkUiLCJOIiwiTk9OIiwiT0UiLCJPVEgiLCJQRyIsIlBTTCIsIlBBRiIsIlBGUCIsIlBGRCIsIlBPUCIsIlBQWSIsIlBDSCIsIlBQRCIsIlBSTyIsIk5BUCIsIlBSSSIsIlJVUCIsIlJFRiIsIlJFUCIsIlJFUyIsIlJUTCIsIlNFUCIsIlNMUCIsIlNVUyIsIlNPQyIsIlNXUCIsIlRYIiwiVFdSIiwiVEVBIiwiVEhEIiwiTEFCIiwiVVNQIiwiVVNUIiwiVU4iLCJVQyIsIlVOSSIsIlVOSyIsIlZFVCIsIldUUCIsIlciKSwNCiAgTGFiZWwgPSBjKCJBY2UgUGFydHkiLCJBbGFza2FuIEluZGVwZW5kZW5jZSBQYXJ0eSIsIkFtZXJpY2FuIEluZGVwZW5kZW50IENvbnNlcnZhdGl2ZSIsIkFtZXJpY2FuIEluZGVwZW5kZW50IFBhcnR5IiwiQW1lcmljYW4gUGFydHkiLCJBbWVyaWNhbiBQZW9wbGUncyBGcmVlZG9tIFBhcnR5IiwiQW1lcmljYW5zIEVsZWN0IiwiQ2l0aXplbnMnIFBhcnR5IiwiQ29tbWFuZG1lbnRzIFBhcnR5IiwiQ29tbW9ud2VhbHRoIFBhcnR5IG9mIHRoZSBVLlMuIiwiQ29tbXVuaXN0IFBhcnR5IiwiQ29uY2VybmVkIENpdGl6ZW5zIFBhcnR5IE9mIENvbm5lY3RpY3V0IiwiQ29uc2VydmF0aXZlIFBhcnR5IiwiQ29uc3RpdHV0aW9uIFBhcnR5IiwiQ29uc3RpdHV0aW9uYWwiLCJDb3VudHJ5IiwiRC5DLiBTdGF0ZWhvb2QgR3JlZW4gUGFydHkiLCJEZW1vY3JhdGljIC1Ob25wYXJ0aXNhbiBMZWFndWUiLCJEZW1vY3JhdGljIFBhcnR5IiwiRGVtb2NyYXRpYy9Db25zZXJ2YXRpdmUiLCJEZW1vY3JhdGljLUZhcm1lci1MYWJvciIsIkRlc2VydCBHcmVlbiBQYXJ0eSIsIkZlZGVyYWxpc3QiLCJGcmVlZG9tIExhYm9yIFBhcnR5IiwiRnJlZWRvbSBQYXJ0eSIsIkdlb3JnZSBXYWxsYWNlIFBhcnR5IiwiR3Jhc3Nyb290cyIsIkdyZWVuIFBhcnR5IiwiR3JlZW4tUmFpbmJvdyIsIkh1bWFuIFJpZ2h0cyBQYXJ0eSIsIkluZGVwZW5kZW5jZSBQYXJ0eSIsIkluZGVwZW5kZW50IiwiSW5kZXBlbmRlbnQgQW1lcmljYW4gUGFydHkiLCJJbmRlcGVuZGVudCBDb25zZXJ2YXRpdmUgRGVtb2NyYXRpYyIsIkluZGVwZW5kZW50IEdyZWVuIiwiSW5kZXBlbmRlbnQgUGFydHkiLCJJbmRlcGVuZGVudCBQYXJ0eSBvZiBEZWxhd2FyZSIsIkluZHVzdHJpYWwgR292ZXJubWVudCBQYXJ0eSIsIkpld2lzaC9DaHJpc3RpYW4gTmF0aW9uYWwiLCJKdXN0aWNlIFBhcnR5IiwiTGEgUmF6YSBVbmlkYSIsIkxhYm9yIFBhcnR5IiwiTGVzcyBGZWRlcmFsIFRheGVzIiwiTGliZXJhbCBQYXJ0eSIsIkxpYmVydGFyaWFuIFBhcnR5IiwiTGliZXJ0eSBVbmlvbiBQYXJ0eSIsIk1vdW50YWluIFBhcnR5IiwiTmF0aW9uYWwgRGVtb2NyYXRpYyBQYXJ0eSIsIk5hdHVyYWwgTGF3IFBhcnR5IiwiTmV3IEFsbGlhbmNlIiwiTmV3IEplcnNleSBDb25zZXJ2YXRpdmUgUGFydHkiLCJOZXcgUHJvZ3Jlc3NpdmUgUGFydHkiLCJObyBQYXJ0eSBBZmZpbGlhdGlvbiIsIk5vIFBhcnR5IFByZWZlcmVuY2UiLCJOb25lIiwiTm9ucGFydGlzYW4iLCJOb24tUGFydHkiLCJPbmUgRWFydGggUGFydHkiLCJPdGhlciIsIlBhY2lmaWMgR3JlZW4iLCJQYXJ0eSBmb3IgU29jaWFsaXNtIGFuZCBMaWJlcmF0aW9uIiwiUGVhY2UgQW5kIEZyZWVkb20iLCJQZWFjZSBBbmQgRnJlZWRvbSBQYXJ0eSIsIlBlYWNlIEZyZWVkb20gUGFydHkiLCJQZW9wbGUgT3ZlciBQb2xpdGljcyIsIlBlb3BsZSdzIFBhcnR5IiwiUGVyc29uYWwgQ2hvaWNlIFBhcnR5IiwiUG9wdWxhciBEZW1vY3JhdGljIFBhcnR5IiwiUHJvZ3Jlc3NpdmUgUGFydHkiLCJQcm9oaWJpdGlvbiBQYXJ0eSIsIlB1ZXJ0byBSaWNhbiBJbmRlcGVuZGVuY2UgUGFydHkiLCJSYXphIFVuaWRhIFBhcnR5IiwiUmVmb3JtIFBhcnR5IiwiUmVwdWJsaWNhbiBQYXJ0eSIsIlJlc291cmNlIFBhcnR5IiwiUmlnaHQgVG8gTGlmZSIsIlNvY2lhbGlzdCBFcXVhbGl0eSBQYXJ0eSIsIlNvY2lhbGlzdCBMYWJvciBQYXJ0eSIsIlNvY2lhbGlzdCBQYXJ0eSIsIlNvY2lhbGlzdCBQYXJ0eSBVLlMuQS4iLCJTb2NpYWxpc3QgV29ya2VycyBQYXJ0eSIsIlRheHBheWVycyIsIlRheHBheWVycyBXaXRob3V0IFJlcHJlc2VudGF0aW9uIiwiVGVhIFBhcnR5IiwiVGhlby1EZW1vY3JhdGljIiwiVS5TLiBMYWJvciBQYXJ0eSIsIlUuUy4gUGVvcGxlJ3MgUGFydHkiLCJVLlMuIFRheHBheWVycyBQYXJ0eSIsIlVuYWZmaWxpYXRlZCIsIlVuaXRlZCBDaXRpemVuIiwiVW5pdGVkIFBhcnR5IiwiVW5rbm93biIsIlZldGVyYW5zIFBhcnR5IiwiV2UgdGhlIFBlb3BsZSIsIldyaXRlLUluIikNCikNCg0KDQoNCmBgYA0KDQpgYGB7cn0NCmNhbmRfZGF0YSA8LSAgcmVhZC5jc3YyKGZpbGUgPSAiQzovVXNlcnMvMTgxMzcvRG93bmxvYWRzL2NhbmRpZGF0ZV9zdW1tYXJ5XzIwMjAuY3N2Iiwgc2VwID0gIiwiICwgKQ0KY2FuZF9kYXRhJFRvdGFsX0NvbnRyaWJ1dGlvbiA8LSBhcy5udW1lcmljKGNhbmRfZGF0YSRUb3RhbF9Db250cmlidXRpb24pDQpjYW5kX2RhdGEkVG90YWxfUmVjZWlwdCA8LSBhcy5udW1lcmljKGNhbmRfZGF0YSRUb3RhbF9SZWNlaXB0KQ0KDQpjYW5kX2RhdGEgPC0gY2FuZF9kYXRhICU+JQ0KICBsZWZ0X2pvaW4ocGFydHlfZGljdGlvbmFyeSwgYnkgPSBjKCJDYW5kX1BhcnR5X0FmZmlsaWF0aW9uIiA9ICJPcmlnaW5hbCIpKSAlPiUNCiAgIyBPcHRpb25hbGx5LCB5b3UgbWlnaHQgd2FudCB0byByZW1vdmUgdGhlIG9yaWdpbmFsIGNvbHVtbiBhbmQgcmVuYW1lIHRoZSBuZXcgb25lDQogIHNlbGVjdCgtQ2FuZF9QYXJ0eV9BZmZpbGlhdGlvbikgJT4lDQogIHJlbmFtZShDYW5kX1BhcnR5X0FmZmlsaWF0aW9uID0gTGFiZWwpDQoNCmVsZWN0aW9uX3Jlc3VsdHMgPC0gcmVhZF9leGNlbCgiQzovVXNlcnMvMTgxMzcvRG93bmxvYWRzL2ZlZGVyYWxlbGVjdGlvbnMyMDIwLnhsc3giKQ0KDQpzZW5hdGVfcmVzdWx0cyA8LSByZWFkX2V4Y2VsKCJDOi9Vc2Vycy8xODEzNy9Eb3dubG9hZHMvZmVkZXJhbGVsZWN0aW9uczIwMjAueGxzeCIsIHNoZWV0ID0gIjEyLiBVUyBTZW5hdGUgUmVzdWx0cyBieSBTdGF0ZSIpDQpob3VzZV9yZXN1bHRzIDwtIHJlYWRfZXhjZWwoIkM6L1VzZXJzLzE4MTM3L0Rvd25sb2Fkcy9mZWRlcmFsZWxlY3Rpb25zMjAyMC54bHN4Iiwgc2hlZXQgPSAiMTMuIFVTIEhvdXNlIFJlc3VsdHMgYnkgU3RhdGUiKQ0KcHJlc19wcmltYXJ5X3Jlc3VsdHMgPC0gcmVhZF9leGNlbCgiQzovVXNlcnMvMTgxMzcvRG93bmxvYWRzL2ZlZGVyYWxlbGVjdGlvbnMyMDIwLnhsc3giLCBzaGVldCA9ICI5LiAyMDIwIFByZXMgR2VuZXJhbCBSZXN1bHRzIikNCmBgYA0KDQpgYGB7cn0NCnNlbmF0ZV9yZXN1bHRzIDwtIHNlbmF0ZV9yZXN1bHRzICU+JQ0KICBtdXRhdGUoV2luX0xvc2UgPSBhcy5udW1lcmljKCdHRSBXaW5uZXIgSW5kaWNhdG9yJyA9PSAiVyIpKQ0KDQpob3VzZV9yZXN1bHRzIDwtIGhvdXNlX3Jlc3VsdHMgJT4lDQogIG11dGF0ZShXaW5fTG9zZSA9IGFzLm51bWVyaWMoJ0dFIFdpbm5lciBJbmRpY2F0b3InID09ICJXIikpDQoNCnByZXNfcHJpbWFyeV9yZXN1bHRzIDwtIHByZXNfcHJpbWFyeV9yZXN1bHRzICU+JQ0KICBtdXRhdGUoV2luX0xvc2UgPSBhcy5udW1lcmljKCdXaW5uZXJfSW5kaWNhdG9yJyA9PSAiVyIpKQ0KYGBgDQoNCmBgYHtyfQ0KY2FuZF9kYXRhIDwtIGNhbmRfZGF0YSAlPiUgZ3JvdXBfYnkoQ2FuZF9QYXJ0eV9BZmZpbGlhdGlvbikgJT4lIGZpbHRlcihUb3RhbF9SZWNlaXB0ID4gMCkNCg0KDQphbGxfZWxlY3Rpb25fcmVzdWx0cyA8LSBiaW5kX3Jvd3Moc2VuYXRlX3Jlc3VsdHMsIGhvdXNlX3Jlc3VsdHMsIHByZXNfcHJpbWFyeV9yZXN1bHRzKQ0KDQpmaW5hbF9kYXRhIDwtIGNhbmRfZGF0YSAlPiUNCiAgbGVmdF9qb2luKGFsbF9lbGVjdGlvbl9yZXN1bHRzLCBieSA9IGMoIkNhbmRfSWQiID0gIkZFQyBJRCIpKQ0KDQoNCmZpbmFsX2RhdGEkV2luX0xvc2VbaXMubmEoZmluYWxfZGF0YSRXaW5fTG9zZSldIDwtIDANCmhlYWQoZmluYWxfZGF0YSkNCg0KbWVyZ2VkX2RhdGEgPC0gZmluYWxfZGF0YSAlPiUNCiAgbXV0YXRlKFRvdGFsX0NvbnRyaWJ1dGlvbiA9IGlmX2Vsc2UoaXMubmEoVG90YWxfQ29udHJpYnV0aW9uKSwgbWVkaWFuKFRvdGFsX0NvbnRyaWJ1dGlvbiwgbmEucm0gPSBUUlVFKSwgVG90YWxfQ29udHJpYnV0aW9uKSkNCg0Kc3VtbWFyeShtZXJnZWRfZGF0YSkNCg0KDQpgYGANCg0KYGBge3J9DQojIEVuc3VyZSBXaW5fTG9zZSBpcyBhIGZhY3RvciBmb3IgbG9naXN0aWMgcmVncmVzc2lvbg0KbWVyZ2VkX2RhdGEkV2luX0xvc2UgPC0gYXMuZmFjdG9yKG1lcmdlZF9kYXRhJFdpbl9Mb3NlKQ0KDQojIEZpdCB0aGUgbW9kZWwNCm1vZGVsIDwtIGdsbShXaW5fTG9zZSB+IFRvdGFsX0NvbnRyaWJ1dGlvbiwgZGF0YSA9IG1lcmdlZF9kYXRhLCBmYW1pbHkgPSBiaW5vbWlhbCgpLGNvbnRyb2wgPSBnbG0uY29udHJvbChtYXhpdCA9IDEwMDAwKSkNCg0KIyBDaGVjayB0aGUgc3VtbWFyeQ0Kc3VtbWFyeShtb2RlbCkNCmBgYA0KDQpgYGB7cn0NCnNldC5zZWVkKDEyMykgICMgZm9yIHJlcHJvZHVjaWJpbGl0eQ0KdHJhaW5pbmdfc2FtcGxlcyA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKG1lcmdlZF9kYXRhJFdpbl9Mb3NlLCBwID0gMC44LCBsaXN0ID0gRkFMU0UpDQoNCnRyYWluX2RhdGEgPC0gbWVyZ2VkX2RhdGFbdHJhaW5pbmdfc2FtcGxlcywgXQ0KdGVzdF9kYXRhIDwtIG1lcmdlZF9kYXRhWy10cmFpbmluZ19zYW1wbGVzLCBdDQoNCiMgUHJlZGljdCBvbiB0ZXN0IHNldA0KcHJlZGljdGlvbnMgPC0gcHJlZGljdChtb2RlbCwgdGVzdF9kYXRhLCB0eXBlID0gInJlc3BvbnNlIikNCnByZWRpY3RlZF9jbGFzcyA8LSBpZl9lbHNlKHByZWRpY3Rpb25zID4gMC41LCAxLCAwKQ0KDQojIEFkanVzdGluZyB0aGUgc2FtcGxpbmcgbWV0aG9kIHRvIGVuc3VyZSBzdHJhdGlmaWNhdGlvbg0KdHJhaW5pbmdfc2FtcGxlcyA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKG1lcmdlZF9kYXRhJFdpbl9Mb3NlLCBwID0gMC44LCBsaXN0ID0gVFJVRSwgdGltZXMgPSAxKQ0KDQp0cmFpbl9kYXRhIDwtIG1lcmdlZF9kYXRhW3RyYWluaW5nX3NhbXBsZXNbWzFdXSwgXQ0KdGVzdF9kYXRhIDwtIG1lcmdlZF9kYXRhWy10cmFpbmluZ19zYW1wbGVzW1sxXV0sIF0NCg0KdGVzdF9kYXRhJFdpbl9Mb3NlIDwtIGZhY3Rvcih0ZXN0X2RhdGEkV2luX0xvc2UsIGxldmVscyA9IGMoIjAiLCAiMSIpKQ0KDQojIEVuc3VyZSBwcmVkaWN0ZWRfY2xhc3MgaXMgYSBmYWN0b3Igd2l0aCBib3RoIGxldmVscw0KcHJlZGljdGVkX2NsYXNzIDwtIGZhY3RvcihwcmVkaWN0ZWRfY2xhc3MsIGxldmVscyA9IGMoIjAiLCAiMSIpKQ0KDQpjb25mdXNpb25NYXRyaXgocHJlZGljdGVkX2NsYXNzLCB0ZXN0X2RhdGEkV2luX0xvc2UpDQoNCiMgQ2FsY3VsYXRlIGFjY3VyYWN5IG9yIG90aGVyIHBlcmZvcm1hbmNlIG1ldHJpY3MNCmFjY3VyYWN5IDwtIHN1bShwcmVkaWN0ZWRfY2xhc3MgPT0gdGVzdF9kYXRhJFdpbl9Mb3NlKSAvIG5yb3codGVzdF9kYXRhKQ0KcHJpbnQocGFzdGUoIkFjY3VyYWN5OiIsIGFjY3VyYWN5KSkNCg0KYGBgDQoNCg0KYGBge3J9DQpjb25Ub3RhbCA8LSBjYW5kX2RhdGEkVG90YWxfQ29udHJpYnV0aW9uIA0KDQpmaWcxIDwtIGNhbmRfZGF0YSAlPiUgDQogIGdncGxvdChhZXMoY29uVG90YWwsIENhbmRfU3RhdGUpKSArIGdlb21fY29sKGFlcyhmaWxsID0gY2FuZF9kYXRhJENhbmRfU3RhdGUpKSArIHNjYWxlX3hfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2RvbGxhcihwcmVmaXggPSAiJCIpKQ0KDQpnZ3Bsb3RseShmaWcxKQ0KYGBgDQpgYGB7cn0NCmNhbmRfYnlfYWZmaWxpYXRpb25fVG90YWxfUmVjZWlwdCA8LSBjYW5kX2RhdGEgJT4lIA0KICBncm91cF9ieShDYW5kX1BhcnR5X0FmZmlsaWF0aW9uKSAlPiUgDQogIGZpbHRlcihUb3RhbF9SZWNlaXB0ID4gMCkgJT4lIA0KICBhcnJhbmdlKFRvdGFsX1JlY2VpcHQpDQoNCg0KY2FuZF9ieV9hZmZpbGlhdGlvbl9Ub3RhbF9SZWNlaXB0IDwtIGRhdGEuZnJhbWUoY2FuZF9ieV9hZmZpbGlhdGlvbl9Ub3RhbF9SZWNlaXB0JENhbmRfUGFydHlfQWZmaWxpYXRpb24sIGNhbmRfYnlfYWZmaWxpYXRpb25fVG90YWxfUmVjZWlwdCRUb3RhbF9SZWNlaXB0KQ0KDQphcmdfZGF0YSA8LSBhZ2dyZWdhdGUoY2FuZF9ieV9hZmZpbGlhdGlvbl9Ub3RhbF9SZWNlaXB0JGNhbmRfYnlfYWZmaWxpYXRpb25fVG90YWxfUmVjZWlwdC5Ub3RhbF9SZWNlaXB0LA0KICBsaXN0KENhdGVnb3J5ID0gY2FuZF9ieV9hZmZpbGlhdGlvbl9Ub3RhbF9SZWNlaXB0JGNhbmRfYnlfYWZmaWxpYXRpb25fVG90YWxfUmVjZWlwdC5DYW5kX1BhcnR5X0FmZmlsaWF0aW9uKSwNCiAgc3VtKQ0KDQphcmdfZGF0YSA8LSBhcmdfZGF0YSAlPiUgdG9wX24oMikNCg0KZ2dwbG90KGFyZ19kYXRhLCBhZXMoeCA9IENhdGVnb3J5LCB5ID0geCkpICsgIGdlb21fY29sKGFlcyhmaWxsID0gQ2F0ZWdvcnkpKSArIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBzY2FsZXM6OmxhYmVsX2RvbGxhcihwcmVmaXggPSAiJCIsIHN1ZmZpeCA9ICIiKSkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBBc3N1bWluZyAnY2FuZF9kYXRhJyBpcyB5b3VyIGRhdGEgZnJhbWUgYW5kIGl0IGhhcyBiZWVuIGxvYWRlZCBpbnRvIHlvdXIgUiBzZXNzaW9uDQpkaXN0aW5jdF9wYXJ0aWVzIDwtIGNhbmRfZGF0YSAlPiUNCiAgc2VsZWN0KENhbmRfUGFydHlfQWZmaWxpYXRpb24pICU+JSAgIyBTZWxlY3QgdGhlIGNvbHVtbiBvZiBpbnRlcmVzdA0KICBkaXN0aW5jdCgpICU+JSAgICAgICAgICAgICAgICAgICAgICAjIEdldCBkaXN0aW5jdC91bmlxdWUgZW50cmllcw0KICBhcnJhbmdlKENhbmRfUGFydHlfQWZmaWxpYXRpb24pICAgICAjIE9wdGlvbmFsOiBhcnJhbmdlIHRoZW0gYWxwaGFiZXRpY2FsbHkNCg0KIyBUbyB2aWV3IHRoZSBkaXN0aW5jdCBwYXJ0eSBhZmZpbGlhdGlvbnMNCnByaW50KGRpc3RpbmN0X3BhcnRpZXMpDQpgYGANCg0KDQpgYGB7cn0NCnJlY2VpcHRfZGF0YSA8LSBjYW5kX2RhdGEgJT4lDQogICAgZ3JvdXBfYnkoQ2FuZF9QYXJ0eV9BZmZpbGlhdGlvbikgJT4lDQogICAgc3VtbWFyaXplKFRvdGFsX1JlY2VpcHQgPSBzdW0oVG90YWxfUmVjZWlwdCwgbmEucm0gPSBUUlVFKSkgJT4lDQogICAgZmlsdGVyKFRvdGFsX1JlY2VpcHQgPiAwKSAlPiUgIA0KICAgIGdncGxvdChhZXMoeCA9IENhbmRfUGFydHlfQWZmaWxpYXRpb24sIHkgPSBUb3RhbF9SZWNlaXB0LCBmaWxsID0gQ2FuZF9QYXJ0eV9BZmZpbGlhdGlvbikpICsNCiAgICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKw0KICAgIHNjYWxlX2ZpbGxfdmlyaWRpcyhkaXNjcmV0ZSA9IFRSVUUsIG9wdGlvbiA9ICJNIikgKw0KICAgIHNjYWxlX3lfbG9nMTAobGFiZWxzID0gbGFiZWxfZG9sbGFyKHNjYWxlID0gMSkpICsNCiAgICBsYWJzKHggPSAiUGFydHkgQWZmaWxpYXRpb24iLA0KICAgICAgICAgeSA9ICJMb2cgb2YgVG90YWwgUmVjZWlwdHMgKERvbGxhcnMpIiwNCiAgICAgICAgIHRpdGxlID0gIlRvdGFsIFJlY2VpcHRzIGJ5IFBhcnR5IEFmZmlsaWF0aW9uIikgKw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IDAuNSkpDQoNCnBsb3RseV9yZWNlaXB0X2RhdGEgPC0gZ2dwbG90bHkocmVjZWlwdF9kYXRhKQ0KcGxvdGx5X3JlY2VpcHRfZGF0YQ0KYGBgDQoNCmBgYHtyfQ0KQ29uZ3Jlc3Npb25hbF9kYXRhIDwtIGNhbmRfZGF0YSAlPiUgDQogIGdyb3VwX2J5KENhbmRfT2ZmaWNlKSAlPiUgDQogIGZpbHRlcihDYW5kX09mZmljZSAhPSAiUCIpICU+JSANCiAgYXJyYW5nZShUb3RhbF9Db250cmlidXRpb24pDQoNCkNvbmdyZXNzaW9uYWxfZGF0YSA8LSBhZ2dyZWdhdGUoQ29uZ3Jlc3Npb25hbF9kYXRhJFRvdGFsX0NvbnRyaWJ1dGlvbiwNCiAgbGlzdChDYXRlZ29yeSA9IENvbmdyZXNzaW9uYWxfZGF0YSRDYW5kX09mZmljZSApLA0KICBzdW0pDQoNCnByZXNpZGVudF9kYXRhIDwtIGNhbmRfZGF0YSAlPiUgDQogIGdyb3VwX2J5KENhbmRfT2ZmaWNlKSAlPiUgDQogIGZpbHRlcihDYW5kX09mZmljZSA9PSAiUCIpICU+JSANCiAgYXJyYW5nZShUb3RhbF9Db250cmlidXRpb24pDQpgYGANCg0KDQpgYGB7cn0NCkNvbmdyZXNzaW9uYWxfZGF0YSAlPiUgZ2dwbG90KGFlcyh4ID0geCwgeSA9IENhdGVnb3J5KSkgKyBnZW9tX2NvbChhZXMoZmlsbCA9IENhdGVnb3J5KSkgKyBzY2FsZV94X2NvbnRpbnVvdXMobGFiZWwgPSBzY2FsZXM6OmxhYmVsX2RvbGxhcihwcmVmaXggPSAiJCIpKQ0KYGBgDQoNCg0KYGBge3J9DQpmaWcxIDwtIGNhbmRfZGF0YSAlPiUNCiAgICBncm91cF9ieShDYW5kX1N0YXRlKSAlPiUNCiAgICBzdW1tYXJpc2UoVG90YWxfQ29udHJpYnV0aW9uID0gc3VtKFRvdGFsX0NvbnRyaWJ1dGlvbikpICU+JQ0KICAgIGZpbHRlcihUb3RhbF9Db250cmlidXRpb24gPiAwKSAlPiUgICMgRmlsdGVyaW5nIG91dCB6ZXJvcw0KICAgIGdncGxvdChhZXMoeCA9IENhbmRfU3RhdGUsIHkgPSBUb3RhbF9Db250cmlidXRpb24sIGZpbGwgPSBDYW5kX1N0YXRlKSkgKw0KICAgIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogICAgc2NhbGVfZmlsbF92aXJpZGlzKGRpc2NyZXRlID0gVFJVRSwgb3B0aW9uID0gIkQiKSArICAjIFVzaW5nIHZpcmlkaXMgZm9yIGRpc2NyZXRlIGNvbG9yIG1hcHBpbmcNCiAgICBzY2FsZV95X2xvZzEwKGxhYmVscyA9IHNjYWxlczo6bGFiZWxfZG9sbGFyKHNjYWxlID0gMSkpICsgICMgRm9ybWF0dGluZyB5LWF4aXMgYXMgZG9sbGFyIHZhbHVlcw0KICAgIHRoZW1lX21pbmltYWwoKSArDQogICAgbGFicyh0aXRsZSA9ICJUb3RhbCBDb250cmlidXRpb25zIGJ5IFN0YXRlIiwNCiAgICAgICAgIHkgPSAiTG9nIG9mIFRvdGFsIENvbnRyaWJ1dGlvbnMgKERvbGxhcnMpIiwNCiAgICAgICAgIHggPSAiU3RhdGUiKSArDQogICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgaGp1c3QgPSAxLCB2anVzdCA9IDAuNSkpICAjIFZlcnRpY2FsIHgtYXhpcyBsYWJlbHMNCg0KIyBDb252ZXJ0IHRvIFBsb3RseSBpbnRlcmFjdGl2ZSBwbG90DQpwbG90bHlfZmlnMSA8LSBnZ3Bsb3RseShmaWcxKQ0KcGxvdGx5X2ZpZzENCg0KYGBgDQoNCg0K